{ open Parser }

rule token = parse
    [' ' '\t' '\r']     { token lexbuf }            (* Whitespace *)
    | "//"              { comment lexbuf }          (* Comments *)
    
    
    (* Primitive types *) 
    | ['0'-'9']+ as lxm { INT(int_of_string lxm) }
    | ['0'-'9']+'.'['0'-'9']* as fl { FLOAT(float_of_string(fl)) }
    | ['0'-'9']*'.'['0'-'9']+ as fl { FLOAT(float_of_string(fl)) }
    | "true"            { BOOLEAN(true) }
    | "false"           { BOOLEAN(false) }
    | ('\"'("\\\""|[^'\"'])*'\"') as st {STRING(st)}
   
    
    (* Grouping symbols *) 
    | '('               { LPAREN }
    | ')'               { RPAREN }
    | "{\r?\n?"         { LCURL }					(* Allow one newline *)
    | '}'               { RCURL }
    | '['               { LBRACE }
    | ']'               { RBRACE }
    | '|'               { BAR }
    
    
    (* Punctuation *)
    | ','               { COMMA }
    | '.'               { DOT }
    | ':'               { COLON }
    | '='               { ASSIGN }


    (* Arithmetic Operators *)
    | '+'               { PLUS }
    | '-'               { MINUS }
    | '*'               { TIMES }
    | '/'               { DIVIDE }
    | '%'               { MOD }


    (* Boolean comparison operators *)
    | "not"             { NOT }
    | "and"             { AND }
    | "or"              { OR }


    (* Inc operators *)
    | "++"              { INCREMENT }
    | "--"              { DECREMENT }


    (* Comparison operators *)
    | "!="              { NEQ }
    | "=="              { EQ }
    | '<'               { LT }
    | ">"               { GT }
    | "<="              { LEQ }
    | ">="              { GEQ }


    (* Update operators *)
    | "+="              { PLUSEQ }
    | "-="              { MINUSEQ }
    | "*="              { TIMESEQ }
    | "/="              { SLASHEQ }


    (* Separators *)
    | "\n"	            { EOL }
    | eof               { EOF }


    (* Keywords *)
    | "if"              { IF }
    | "elseif"          { ELSEIF }
    | "else"            { ELSE }
    | "while"           { WHILE }
    | "for"             { FOR }
    | "return"          { RETURN }
    | "?"               { RULES }


    (* Built in functions *)
    | "CAST"            { CAST }
    | "PLAY"            { PLAY }
    | "INPUT"           { INPUT }
    | "OUTPUT"          { OUTPUT }


    (* Type keywords *)
    | "int"             { INTTYPE }
    | "float"           { FLOATTYPE }
    | "string"          { STRINGTYPE }
    | "bool"            { BOOLTYPE }


    (* Identifier *)
    | ['a'-'z' 'A'-'Z']['a'-'z' 'A'-'Z' '0'-'9' '_']* as lxm    { ID(lxm) }  


    (* Error *)
    | _ as char         { raise (Failure("illegal character " ^ Char.escaped char)) }


and comment = parse
  "\r?\n" { token lexbuf }
| _    { comment lexbuf }
